<!-- eslint-disable no-unused-vars -->
<template>
  <div :class="`tab-header`">
    <div id="editor">
      <Input
        :class="`button-common`"
        type="file"
        ref="fielinput"
        accept=".pdf"
        id="fielinput"
        @change="uploadFile"
      />
      <Button :class="`button-common`" v-if="isSign" @click="handleSign">点击预览</Button>
      <Button :class="`button-common`" v-else @click="handleSign">点击签名</Button>
      <Button :class="`button-common`" @click="handleUndo">撤回</Button>
      <Button :class="`button-common`" @click="handleClear">清除</Button>
      <Button :class="`button-common`" @click="savePDF">下载PDF</Button>
    </div>
    <div>
      <div id="parentDiv1">
        <div ref="contentDiv" id="contentDiv"></div>
      </div>
      <div id="parentDiv2">
        <div ref="signContentDiv" id="signContentDiv"></div>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
  import { Button, Input } from 'ant-design-vue';
  import { defineComponent, ref } from 'vue';
  import SmoothSignature from 'smooth-signature';
  import * as pdfJS from 'pdfjs-dist';
  import * as pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
  import { PDFDocument } from 'pdf-lib';

  pdfJS.GlobalWorkerOptions.workerSrc = pdfjsWorker;

  export default defineComponent({
    components: { Button, Input },
    setup() {
      const fielinput = ref(null);
      const signContentDiv = ref(null);
      const contentDiv = ref(null);

      //签名相关
      const isSign = ref(false);
      const canvass = ref([]);
      const signCanvass = ref([]);
      const signatures = ref([]);
      const historys = ref([]);

      //PDF展示相关
      const pdfData = ref(null);
      const base64 = ref(null);
      const scale = ref(2);

      //上传文件
      const uploadFile = (e: Event) => {
        // 断言为HTMLInputElement
        const target = e.target as HTMLInputElement;
        const files = target.files;
        let reader = new FileReader();
        reader.readAsDataURL(files[0]);
        reader.onload = () => {
          base64.value = reader.result;
          let data = atob(reader.result.substring(reader.result.indexOf(',') + 1));
          loadPdfData(data);
        };
      };

      //加载PDF
      function loadPdfData(data) {
        removeChild();
        isSign.value = false;
        canvass.value = [];
        signCanvass.value = [];
        signatures.value = [];
        // 引入pdf.js的字体，如果没有引用的话字体会不显示
        let CMAP_URL = 'https://unpkg.com/pdfjs-dist@2.0.943/cmaps/';
        //读取base64的pdf流文件
        pdfData.value = pdfJS.getDocument({
          data: data, // PDF base64编码
          cMapUrl: CMAP_URL,
          cMapPacked: true,
        });
        renderAllPages();

        //两个DIV协同滚动
        var div1 = document.getElementById('parentDiv1');
        var div2 = document.getElementById('parentDiv2');
        div1.addEventListener('scroll', function () {
          div2.scrollLeft = div1.scrollLeft;
          div2.scrollTop = div1.scrollTop;
        });

        div2.addEventListener('scroll', function () {
          div1.scrollLeft = div2.scrollLeft;
          div1.scrollTop = div2.scrollTop;
        });
      }

      function removeChild() {
        var content = contentDiv.value;
        var child = content.lastElementChild;
        while (child) {
          content.removeChild(child);
          child = content.lastElementChild;
        }

        var signContent = signContentDiv.value;
        var child2 = signContent.lastElementChild;
        while (child2) {
          signContent.removeChild(child2);
          child2 = signContent.lastElementChild;
        }
      }
      //渲染全部canvas
      function renderAllPages() {
        pdfData.value.promise.then((pdf) => {
          for (let i = 1; i <= pdf.numPages; i++) {
            pdf.getPage(i).then((page) => {
              // 获取DOM中为预览PDF准备好的canvasDOM对象
              let viewport = page.getViewport(scale.value);
              var canvas = document.createElement('canvas');
              var sighCanvas = document.createElement('canvas');
              canvas.height = viewport.height;
              canvas.width = viewport.width;

              sighCanvas.height = viewport.height;
              sighCanvas.width = viewport.width;

              let ctx = canvas.getContext('2d');
              let renderContext = {
                canvasContext: ctx,
                viewport: viewport,
              };
              page.render(renderContext).then(() => {});
              initSignatureCanvas(sighCanvas);

              canvass.value.push(canvas);
              signCanvass.value.push(sighCanvas);
              contentDiv.value.appendChild(canvas);
              signContentDiv.value.appendChild(sighCanvas);
            });
          }
        });
      }
      //初始化签名操作方法
      const initSignatureCanvas = (canvas) => {
        const optionSign = {
          width: canvas.width,
          height: canvas.height,
          canDraw: isSign,
          maxHistoryLength: 100, //最大历史记录
        };

        const signature = new SmoothSignature(canvas, optionSign);
        signature.removeListener();
        signature.addHistory = function () {
          if (!signature.maxHistoryLength || !signature.canAddHistory) return;
          signature.canAddHistory = false;
          signature.historyList.push(signature.canvas.toDataURL());
          signature.historyList = signature.historyList.slice(-signature.maxHistoryLength);
          historys.value.push(signature);
        };
        signatures.value.push(signature);
      };

      // 签名预览转换
      const handleSign = () => {
        isSign.value = !isSign.value;
        if (signatures.value && signatures.value.length > 0) {
          if (isSign.value) {
            for (let i = 0; i < signatures.value.length; i++) {
              signatures.value[i].addListener();
            }
          } else {
            // signature.value.removeListener();
            for (let i = 0; i < signatures.value.length; i++) {
              signatures.value[i].removeListener();
            }
          }
        }
      };
      // 清除所有
      const handleClear = async () => {
        while (historys.value && historys.value.length > 0) {
          handleUndo();
        }
      };
      // 后退操作
      const handleUndo = () => {
        if (historys.value && historys.value.length > 0) {
          const signatureList = historys.value;
          let signature = signatureList.pop();
          signature.undo();
          historys.value = signatureList;
        }
      };
      // 下载PDF
      const savePDF = async () => {
        const pdfDoc = await PDFDocument.load(base64.value);
        const pages = pdfDoc.getPages();
        for (let i = 0; i < pages.length; i++) {
          const eleImgCover = await pdfDoc.embedPng(signCanvass.value[i].toDataURL('image/PNG'));
          pages[i].drawImage(eleImgCover, {
            x: 0,
            y: 0,
            width: eleImgCover.width / scale.value,
            height: eleImgCover.height / scale.value,
          });
        }
        const pdfBytes = await pdfDoc.save();
        saveBlob(pdfBytes, 'TestPdf');
      };
      //保存 bolb流
      function saveBlob(data, fileName) {
        if (typeof window.navigator.msSaveBlob !== 'undefined') {
          window.navigator.msSaveBlob(
            new Blob([data], { type: 'application/pdf' }),
            fileName + '.pdf',
          );
        } else {
          let url = window.URL.createObjectURL(new Blob([data], { type: 'application/pdf' })); //定义下载的链接
          let link = document.createElement('a'); //创建一个超链接元素
          link.style.display = 'none'; //隐藏该元素
          link.href = url; //创建下载的链接
          link.setAttribute('download', fileName + '.pdf');
          document.body.appendChild(link);
          link.click(); //点击下载
          document.body.removeChild(link); //下载完成移除元素
          window.URL.revokeObjectURL(url); //释放掉blob对象
        }
      }

      return {
        fielinput,
        uploadFile,
        signContentDiv,
        contentDiv,
        isSign,
        handleSign,
        handleUndo,
        handleClear,
        savePDF,
      };
    },
    mounted() {},
  });
</script>
<style lang="less" scoped>
  .tab-header {
    background: rgb(146, 175, 138);
    padding-left: 1%;
    padding-right: 1%;
  }
  .button-common {
    margin-right: 2px;
    max-width: 200px;
  }
  #parentDiv1 {
    position: absolute;
    overflow: auto;
    top: 5%;
    bottom: 1%;
    display: inline-block;
  }
  #parentDiv2 {
    position: absolute;
    overflow: auto;
    top: 5%;
    bottom: 1%;
    display: inline-block;
  }
</style>
